// Copyright (c) 2025, 大连理工大学 (Dalian University of Technology)
//
// Licensed under the Mulan PSL v2.
// You can use this file according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of the License at
//
//     http://license.coscl.org.cn/MulanPSL2
//
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. SEE THE MULAN PSL v2
// FOR MORE DETAILS.

/*
 * @Author: qiulin_JXGM ql1746365080@gmail.com
 * @Date: 2024-11-07 15:12:23
 * @LastEditors: qiulin 1746365080@qq.com
 * @LastEditTime: 2025-01-02 17:10:52
 * @FilePath: \SGFEM\Import\BDFImport\BulkData\Element\CWELDParse.cpp
 */

#include "CWELDParser.h"

#include <algorithm>
#include <cstdint>
#include <iostream>

#include <boost/algorithm/string.hpp>

#include "Utility/Logging/SGLogger.h"

#include "DataStructure/Input/Element/CWELDData.h"

#include "DBManager/DBServiceFactory.h"
#include "DBManager/IService/Input/Element/IElementService.h"

#include "Import/BDFImport/BDFImport.h"
#include "Import/BDFImport/BDFParserBase.h"
BULKDATA_ENTRY_PARSER_REG (CWELD);

using namespace SG::DBManager;
using namespace SG::Import;
using namespace SG::Import::BDF;
using namespace SG::DataStructure;
/*
// file://./../../Doc/MarkDown/BulkData/CWELD/CWELD.md>
*/
// 以下需要修改

enum CWELDIndex : std::uint8_t
{
    CWELDIndex_EWID     = 1,
    CWELDIndex_PWID     = 2,   ///< property Id
    CWELDIndex_GS       = 3,   ///< 焊接节点id
    CWELDIndex_FORMAT   = 4,   ///< 连接形式
    CWELDIndex_GA       = 5,   ///< 表面A和表面B上穿刺点的网格点标识编号
    CWELDIndex_GB       = 6,   ///< 表面A和表面B上穿刺点的网格点标识编号
    CWELDIndex_GRIDTYPE = 7,   ///< FORMAT=GRIDID时的类型
    CWELDIndex_MCID     = 8,   ///< 单元刚度坐标系
    CWELDIndex_E1ORP1   = 11,  ///< 单元ID1
    CWELDIndex_E2ORP2   = 12,  ///< 单元ID2
    CWELDIndex_XS       = 21,  ///< 基本坐标系中的点焊位置坐标
    CWELDIndex_YS       = 22,  ///< 基本坐标系中的点焊位置坐标
    CWELDIndex_ZS       = 23,  ///< 基本坐标系中的点焊位置坐标
};

namespace
{
    FEM::CWELDFormats getFormat (std::string& formatStr)
    {
        static std::map<std::string, FEM::CWELDFormats> formatMap = { { "GRIDID", FEM::CWELDFormats::FORMAT_GridID },
                                                                      { "ALIGN", FEM::CWELDFormats::FORMAT_ALign },
                                                                      { "ELEMID", FEM::CWELDFormats::FORMAT_ElemID },
                                                                      { "ELPAT", FEM::CWELDFormats::FORMAT_ElPat },
                                                                      { "PARTPAT", FEM::CWELDFormats::FORMAT_PartPat } };
        boost::trim (formatStr);
        auto iter = formatMap.find (formatStr);
        if (iter == formatMap.end ())
        {
            throw std::runtime_error ("getFormat have bad para");
        }
        return iter->second;
    }

    Common::I64 getGRIDTYPE (std::string& GridTypeStr)
    {
        static std::map<std::string, Common::I64> GridTypeMap = {
            { "QQ", 0X00020002 }, { "QT", 0X00020001 }, { "TQ", 0X00010002 },
            { "TT", 0X00010001 }, { "Q", 0X00020000 },  { "T", 0X00010000 },
        };

        boost::trim (GridTypeStr);
        auto iter = GridTypeMap.find (GridTypeStr);
        if (iter == GridTypeMap.end ())
        {
            throw std::runtime_error ("getGRIDTYPE have bad para");
        }
        return iter->second;
    }

    void parsePartPat (std::vector<std::string>& dividedEntryInfo, FEM::CWELDData& tempCWELD)
    {
        for (size_t i = 11; i < dividedEntryInfo.size (); i++)
        {
            auto       curStrKey = dividedEntryInfo[i];
            bool const isEmpty   = is_all_space (curStrKey);
            if (isEmpty)
            {
                continue;
            }

            switch (i)
            {
            case CWELDIndex_E1ORP1:
                tempCWELD.m_PIdA = convertToI64 (curStrKey);
                break;
            case CWELDIndex_E2ORP2:
                tempCWELD.m_PIdB = convertToI64 (curStrKey);
                break;
            case CWELDIndex_XS:
                tempCWELD.m_XYZ[0] = convertToReal (curStrKey);
                break;
            case CWELDIndex_YS:
                tempCWELD.m_XYZ[1] = convertToReal (curStrKey);
                break;
            case CWELDIndex_ZS:
                tempCWELD.m_XYZ[2] = convertToReal (curStrKey);
                break;
            default:
                break;
            }
        }
    }

    void parseElPatElemID (std::vector<std::string>& dividedEntryInfo, FEM::CWELDData& tempCWELD)
    {
        for (size_t i = 11; i < dividedEntryInfo.size (); i++)
        {
            auto       curStrKey = dividedEntryInfo[i];
            bool const isEmpty   = is_all_space (curStrKey);
            if (isEmpty)
            {
                continue;
            }

            switch (i)
            {
            case CWELDIndex_E1ORP1:
                tempCWELD.m_ShIdA = convertToI64 (curStrKey);
                break;
            case CWELDIndex_E2ORP2:
                tempCWELD.m_ShIdB = convertToI64 (curStrKey);
                break;
            case CWELDIndex_XS:
                tempCWELD.m_XYZ[0] = convertToReal (curStrKey);
                break;
            case CWELDIndex_YS:
                tempCWELD.m_XYZ[1] = convertToReal (curStrKey);
                break;
            case CWELDIndex_ZS:
                tempCWELD.m_XYZ[2] = convertToReal (curStrKey);
                break;
            default:
                break;
            }
        }
    }

    void parseGridID (std::vector<std::string>& dividedEntryInfo, FEM::CWELDData& tempCWELD)
    {
        for (size_t i = 0; i < 8; i++)
        {
            auto       curStrKey = dividedEntryInfo[11 + i];
            bool const isEmpty   = is_all_space (curStrKey);
            if (isEmpty)
            {
                continue;
            }

            tempCWELD.m_GUpper[i] = convertToI64 (curStrKey);
        }
        for (size_t i = 0; i < 8; i++)
        {
            auto       curStrKey = dividedEntryInfo[21 + i];
            bool const isEmpty   = is_all_space (curStrKey);
            if (isEmpty)
            {
                continue;
            }

            tempCWELD.m_GLower[i] = convertToI64 (curStrKey);
        }
    }

}  // namespace
SG::DataStructure::Common::Status BDF::BULKDATA::ParseCWELD (const std::shared_ptr<SG::DBManager::DBServiceFactory>& dbServiceFactory,
                                                             std::vector<std::string>&                               dividedEntryInfo)
{
    // 创建临时的CWELD数据对象
    FEM::CWELDData tempCWELD;

    // TODO(bug 001) 正确填写m_dominId，当前默认赋值为1
    tempCWELD.m_domainId = 1;

    // 获取Format
    auto format        = getFormat (dividedEntryInfo[CWELDIndex_FORMAT]);
    tempCWELD.m_format = static_cast<Common::I64> (format);
    tempCWELD.m_g[0]   = getVirtualGridId ();
    tempCWELD.m_g[1]   = getVirtualGridId ();

    // 解析第一行
    for (auto i = 1; i < 9; i++)
    {
        auto       curStrKey = dividedEntryInfo[i];
        bool const isEmpty   = is_all_space (curStrKey);
        if (isEmpty)
        {
            continue;
        }
        switch (i)
        {
        case CWELDIndex_EWID:
            tempCWELD.m_id = convertToI64 (curStrKey);
            break;
        case CWELDIndex_PWID:
            tempCWELD.m_pId = convertToI64 (curStrKey);
            break;
        case CWELDIndex_GS:
            tempCWELD.m_Gs = convertToI64 (curStrKey);
            break;
        case CWELDIndex_GA:
            tempCWELD.m_g[0] = convertToI64 (curStrKey);
            break;
        case CWELDIndex_GB:
            tempCWELD.m_g[1] = convertToI64 (curStrKey);
            break;
        case CWELDIndex_GRIDTYPE:
            tempCWELD.m_type = getGRIDTYPE (curStrKey);
            break;
        case CWELDIndex_MCID:
            tempCWELD.m_mCId = convertToI64 (curStrKey);
            break;
        default:
            break;
        }
    }

    // 解析第二轮
    switch (format)
    {
    case FEM::CWELDFormats::FORMAT_GridID:
        parseGridID (dividedEntryInfo, tempCWELD);
        break;
    case FEM::CWELDFormats::FORMAT_ElemID:
    case FEM::CWELDFormats::FORMAT_ElPat:
        parseElPatElemID (dividedEntryInfo, tempCWELD);
        break;
    case FEM::CWELDFormats::FORMAT_PartPat:
        parsePartPat (dividedEntryInfo, tempCWELD);
        break;
    default:
        break;
    }

    // 将解析后的CWELD数据添加到数据库
    return dbServiceFactory->get<IElementService> ()->Add (tempCWELD);
}
